home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / drivers2.zip / NB.ASM < prev    next >
Assembly Source File  |  1992-01-06  |  20KB  |  855 lines

  1. version equ     4
  2.  
  3.         include defs.asm        ;SEE ENCLOSED COPYRIGHT MESSAGE
  4. NCB_NOWAIT         equ 80h         ;  Command wait flag
  5.  
  6. NCB_RESET          equ 32h         ;  Reset adapter
  7. NCB_CANCEL         equ 35h         ;  Cancel command
  8. NCB_STATUS         equ 33h         ;  Get NETBIOS intf status
  9. NCB_UNLINK         equ 70h         ;  Unlink   (RPL)
  10. NCB_ADDNAME        equ 30h         ;  Add name
  11. NCB_ADDGNAME       equ 36h         ;  Add group name
  12. NCB_DELNAME        equ 31h         ;  Delete name
  13. NCB_FINDNAME       equ 78h         ;  Find name
  14. NCB_CALL           equ 10h         ;  Call
  15. NCB_LISTEN         equ 11h         ;  Listen
  16. NCB_HANGUP         equ 12h         ;  Hang up
  17. NCB_SEND           equ 14h         ;  Send
  18. NCB_CHSEND         equ 17h         ;  Chain send
  19. NCB_RECEIVE        equ 15h         ;  Receive
  20. NCB_RECANY         equ 16h         ;  Receive any
  21. NCB_SESSTATUS      equ 34h         ;  Get session status
  22. NCB_SDATAGRAM      equ 20h         ;  Send datagram
  23. NCB_SBROADCAST     equ 22h         ;  Send broadcast
  24. NCB_RDATAGRAM      equ 21h         ;  Receive datagram
  25. NCB_RBROADCAST     equ 23h         ;  Receive broadcast
  26. NCB_TRACE          equ 79h         ;  Start trace
  27.  
  28. ;
  29. ; Network Control Block structure
  30. ;
  31. ncb             struc
  32. ncb_command     db ?
  33. ncb_retcode     db ?
  34. ncb_lsn         db ?
  35. ncb_num         db ?
  36. ncb_buffer      dd ?
  37. ncb_length      dw ?
  38. ncb_callname    db 16 dup(?)
  39. ncb_name        db 16 dup(?)
  40. ncb_rto         db ?
  41. ncb_sto         db ?
  42. ncb_post        dd ?
  43. ncb_lana_num    db ?
  44. ncb_cmd_cplt    db ?
  45. ncb_reserve     db 14 dup(?)
  46. ncb             ends
  47.  
  48. ;
  49. ; ARP packet structure
  50. ;
  51. arp        struc 
  52. arp_hw        dw ?         ; Hardware address length, bytes 
  53. arp_prot    dw ?         ; Protocol type 
  54. arp_hwalen    db ?         ; hardware address length, bytes 
  55. arp_pralen     db ?         ; Length of protocol address 
  56. arp_opcode      dw ?         ; ARP opcode (request/reply) 
  57. arp_shwaddr    db 6 dup(?)    ; Sender hardware address field 
  58. arp_sprotaddr    dd ?        ; Sender Protocol address field 
  59. arp_thwaddr    db 6 dup(?)    ; Target hardware address field 
  60. arp_tprotaddr    dd ?        ; Target protocol address field 
  61. arp        ends
  62.  
  63. code    segment word public
  64.         assume  cs:code, ds:code
  65. ;***************************************************************
  66. prefix          db "TCPIP"
  67.  
  68.         public  int_no
  69. int_no  db      0,0,0,0
  70. ip_adress       dw      2 dup(0)
  71. rq_size         dw      3
  72. padding         dd      0
  73.  
  74.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  75. driver_class    db      1,0             ;from the packet spec
  76. driver_type     db      0               ;from the packet spec
  77. driver_name     db      'netbios',0     ;name of the driver.
  78. driver_function    db    2
  79. parameter_list    label    byte
  80.     db    1            ;major rev of packet driver
  81.     db    9            ;minor rev of packet driver
  82.     db    14            ;length of parameter list
  83.     db    EADDR_LEN        ;length of MAC-layer address
  84.     dw    1500            ;MTU, including MAC headers
  85.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  86.     dw    0            ;(# of back-to-back MTU rcvs) - 1
  87.     dw    0            ;(# of successive xmits) - 1
  88. int_num    dw    0            ;Interrupt # to hook for post-EOI
  89.                     ;processing, 0 == none,
  90.  
  91.     public    rcv_modes
  92. rcv_modes    dw    4        ;number of receive modes in our table.
  93.         dw    0,0,0,rcv_mode_3
  94.  
  95. lana_num        db 0
  96. local_ncb_num   db 0              ; handle returned by add_name
  97.  
  98.  
  99.         public  nbsend, nbrcv1, nbrcv2, rcv_buffer1 ; MAP
  100. nbsend          ncb <>
  101. nbrcv1          ncb <>
  102. nbrcv2          ncb <>
  103.  
  104.  
  105. MAX_DG          equ 1500 
  106. rcv_buffer1     db MAX_DG dup(?)
  107.  
  108.     public    as_send_pkt
  109. ; The Asynchronous Transmit Packet routine.
  110. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  111. ;   interrupts possibly enabled.
  112. ; Exit with nc if ok, or else cy if error, dh set to error number.
  113. ;   es:di and interrupt enable flag preserved on exit.
  114. as_send_pkt:
  115.     ret
  116.  
  117.     public    drop_pkt
  118. ; Drop a packet from the queue.
  119. ; Enter with es:di -> iocb.
  120. drop_pkt:
  121.     assume    ds:nothing
  122.     ret
  123.  
  124.     public    xmit
  125. ; Process a transmit interrupt with the least possible latency to achieve
  126. ;   back-to-back packet transmissions.
  127. ; May only use ax and dx.
  128. xmit:
  129.     assume    ds:nothing
  130.     ret
  131.  
  132.  
  133. ;
  134. ; recv_find() requires a pointer to the Ethernet packet type.  Since
  135. ; the incoming packet does not contain an Ethernet packet type field,
  136. ; memory must be allocated to hold the Ethernet packet type.  Space is
  137. ; required for both IP and ARP types.
  138. ;
  139. ip_type        label    byte
  140.         db    08
  141.         db    00    
  142.  
  143. arp_type    label    byte
  144.         db    08
  145.         db    06    
  146.  
  147. gw_switch    db    00
  148.  
  149.  
  150.         public  send_pkt
  151. send_pkt:
  152.         assume ds: nothing
  153. ;enter with ds:si -> packet, cx = packet length.
  154. ;exit with nc if ok, or else cy if error, dh set to error number.
  155.         push    es
  156.         push    bx
  157.         push    ds
  158.  
  159. ;strip off Ethernet header
  160.     add    si,12
  161.     mov    ax, word ptr ds:[si]
  162.     add    si,2
  163.     sub    cx,14
  164. ;
  165. ; Check packet type.  If an ARP packet then construct an ARP reply
  166. ; packet. Otherwise, process the incoming IP packet.
  167. ;
  168.     cmp    ax,0608h
  169.     jne    noarp
  170.     call    arp_reply
  171.     jmp    send_ok
  172. noarp:
  173.     
  174.         push    cs
  175.         pop     es
  176. ;
  177. ; Set up NCB for a "SEND DATAGRAM" operation
  178. ;
  179.         mov     bx,offset cs:nbsend
  180.  
  181.         mov     cs:[bx].ncb_buffer.offs,si
  182.         mov     ax,ds
  183.         mov     cs:[bx].ncb_buffer.segm,ds
  184.         mov     cs:[bx].ncb_length,cx
  185.  
  186.         push    bx
  187.         lea     di,cs:nbsend.ncb_callname
  188. ;
  189. ; If gateway switch set then contruct NETBIOS name based on the destination
  190. ; IP address in the IP packet. Otherwise, construct the NETBIOS name
  191. ; based on the destination Ethernet address.
  192. ;
  193.     mov    al,gw_switch
  194.     cmp    al,0
  195.     je    use_hw_addr
  196.     mov    bx, word ptr ds:[si+16]
  197.     mov    dx, word ptr ds:[si+18]
  198.     jmp    conv_addr
  199. use_hw_addr:
  200.     mov    bx, word ptr ds:[si-12]
  201.     mov    dx, word ptr ds:[si-10]
  202. conv_addr:
  203.         push    cs
  204.         pop     ds
  205.         call    ip_to_nbname
  206.         pop     bx
  207. ;
  208. ; Pass "Send Datagram" NCB to NETBIOS
  209. ;
  210.         int     5ch
  211. ;
  212. ; If "Send Datagram" operation is unsuccessful then print return code and
  213. ; set carry bit.  Otherwise, clear the carry bit.
  214. ;
  215.         cmp     al,0
  216.         jz      send_ok
  217.         add     ax,32
  218.         call    tty
  219.         mov     al,'S'
  220.         call    tty
  221.         stc
  222.         jmp     send_done
  223. send_ok:
  224.         clc
  225. send_done:
  226.         pop     ds
  227.         pop     bx
  228.         pop     es
  229.         ret
  230. ;
  231. ; Formulate a dummy ARP reply packet.  ds:si points at the incoming
  232. ; IP packet.
  233. ;
  234. arp_reply:
  235. ;
  236. ; Save the registers.  Not sure that we need to but it works and I 
  237. ; don't want to change it right now.
  238. ;
  239.     push    ds
  240.     push    es
  241.     push    si
  242.     push    di
  243.     push    cx
  244. ;
  245. ; Check to see if the ARP request is to find the hardware address
  246. ; of the local host.  If so, then don't formulate a reply packet.
  247. ;
  248.     mov    cx,4
  249.     mov    ax,si
  250.     mov    di,ax
  251.     mov    ax,ds
  252.     mov    es,ax
  253.     add    di,arp_sprotaddr
  254.     add    si,arp_tprotaddr
  255.     repe    cmpsb            ; Compare source and target
  256.                     ; protocol address
  257.     jnz    arp_reply_2
  258.     pop    cx
  259.     pop    di
  260.     pop    si
  261.     pop    es
  262.     pop    ds
  263.     ret
  264. arp_reply_2:
  265. ;
  266. ; Restore registers.
  267. ;
  268.     pop    cx
  269.     pop    di
  270.     pop    si
  271.     push    si
  272.     push    di
  273.     push    cx
  274. ;
  275. ; Restore Ethernet header.
  276. ;
  277.     add    cx,14
  278.     sub    si,14 
  279. ;
  280. ; Ask application layer for a memory buffer in which to store
  281. ; incoming packet.
  282. ;
  283.     push    ds
  284.     push    si            ;save si in case we reject it.
  285.     push    bx
  286.     push    cx
  287.  
  288.     mov    ax,cs
  289.     mov    es,ax
  290.     mov    ds,ax
  291.     mov    di, offset arp_type
  292.     mov    dl,cs:driver_class
  293.     call    recv_find        ;look up our type.
  294.     pop    cx
  295.     pop    bx
  296.     pop    si
  297.     pop    ds
  298.  
  299.     mov    ax,es            ;is this pointer null?
  300.     or    ax,di
  301.     je    arp_reply_1        ;yes - just free the frame.
  302.  
  303.     push    cx
  304.     push    es
  305.     push    di
  306. ;
  307. ; Save si,di for future use.
  308. ;
  309.     mov    bx,si
  310.     mov    dx,di
  311. ;
  312. ; Set up ARP Reply by first copying the ARP Request packet.
  313. ;
  314.     cld
  315.     rep    movsb
  316. ;
  317. ; Skip Ethernet header
  318. ;
  319.     add    bx,14
  320.     add     dx,14
  321. ;
  322. ; Swap target and source protocol addresses from ARP request to ARP 
  323. ; reply packet.
  324. ;
  325.     mov    si,bx
  326.     mov    di,dx    
  327.     mov    cx,4
  328.     add    si,arp_tprotaddr
  329.     add    di,arp_sprotaddr
  330.     rep    movsb
  331.  
  332.     mov    si,bx
  333.     mov    di,dx
  334.     mov    cx,4
  335.     add    si,arp_sprotaddr
  336.     add    di,arp_tprotaddr
  337.     rep    movsb
  338. ;
  339. ; Swap target and source hardware addresses from ARP request to ARP 
  340. ; reply packet.
  341. ;
  342.     mov    si,bx
  343.     mov    di,dx
  344.     mov    cx,6
  345.     add    si,arp_shwaddr
  346.     add    di,arp_thwaddr
  347.     rep    movsb
  348. ;
  349. ; Load source hardware address in ARP reply packet.
  350. ;
  351.     mov    si,bx
  352.     mov    di,dx
  353.     add    di,arp_shwaddr
  354.     mov    es:[di],word ptr 0000h
  355.     add    di,2
  356.     mov    cx,4
  357.     add    si,arp_tprotaddr    ; Set Ethernet address in ARP reply
  358.                     ; to target IP address
  359.     rep    movsb
  360. ;
  361. ; Set opcode to REPLY.
  362. ;
  363.     mov    di,dx
  364.     mov    word ptr es:[di].arp_opcode,0200h
  365. ; Give ARP reply packet that has been constructed to the application
  366. ; layer.
  367. ;
  368.     pop    si
  369.     pop    ds
  370.     pop    cx
  371.     assume    ds:nothing
  372.  
  373.     call    recv_copy
  374.     assume    ds:code
  375.  
  376. arp_reply_1:
  377.  
  378.     pop    cx
  379.     pop    di
  380.     pop    si
  381.     pop    es
  382.     pop    ds
  383.  
  384.     ret
  385.  
  386.         public  get_address
  387. get_address:
  388. ;get the address of the interface.
  389. ;enter with es:di -> place to get the address, cx = size of address buffer.
  390. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  391.  
  392.     push    bx
  393. ;
  394. ; Copy psuedo-Ethernet address into buffer allocated by the application
  395. ; layer.  Set Ethernet address to host IP address.
  396. ;
  397.     mov    es:[di],word ptr 0000h
  398.         mov     bx,cs:ip_adress
  399.     mov    es:[di+2],bx
  400.     mov    bx,cs:ip_adress+2
  401.     mov    es:[di+4],bx
  402. ;
  403. ; Set size of psuedo-Ethernet address to be returned.
  404. ;
  405.     mov    cx,6
  406.     pop    bx
  407.     clc
  408.         ret
  409.  
  410.  
  411.     public    set_address
  412. set_address:
  413. ;enter with ds:si -> Ethernet address, CX = length of address.
  414. ;exit with nc if okay, or cy, dh=error if any errors.
  415.     assume    ds:nothing
  416.     ret
  417.  
  418.  
  419. rcv_mode_3:
  420. ;receive mode 3 is the only one we support, so we don't have to do anything.
  421.     ret
  422.  
  423.  
  424.     public    set_multicast_list
  425. set_multicast_list:
  426. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  427. ;return nc if we set all of them, or cy,dh=error if we didn't.
  428.     mov    dh,NO_MULTICAST
  429.     stc
  430.     ret
  431.  
  432.  
  433.     public    terminate
  434. terminate:
  435.     ret
  436.  
  437.         public  reset_interface
  438. reset_interface:
  439. ;reset the interface.
  440.         ret
  441.  
  442.  
  443. ;called when we want to determine what to do with a received packet.
  444. ;enter with cx = packet length, es:di -> packet type.
  445.         extrn   recv_find: near
  446.  
  447. ;called after we have copied the packet into the buffer.
  448. ;enter with ds:si ->the packet, cx = length of the packet.
  449.         extrn   recv_copy: near
  450.  
  451.         extrn   count_in_err: near
  452.         extrn   count_out_err: near
  453.         extrn   dwordout: near
  454.         extrn   error: near
  455.  
  456.         public  recv
  457. recv:
  458. ;called from the recv isr.  All registers have been saved, and ds=cs.
  459. ;Upon exit, the interrupt will be acknowledged.
  460.         assume  ds:code
  461.         ret
  462.  
  463.         public nbint  ; MAP
  464. nbint   proc far
  465.         push ds
  466. ;
  467. ; Set data segment to code segment so that we can reference local
  468. ; variables.
  469. ;
  470.         push cs
  471.         pop  ds
  472. ;
  473. ; Retrieve size of received packet
  474. ;
  475.         mov  cx,[bx].ncb_length
  476. ;
  477. ; Check return code.  If there was an error then don't process the
  478. ; packet any further.
  479. ;
  480.         mov  al,[bx].ncb_retcode
  481.         cmp  al,0               ; ok
  482.         jnz  bad_nbint
  483. ;
  484. ; Add Ethernet header.  As well, ensure that minimum packet size is 60
  485. ; bytes; some application packages actually check for minimum packet size.
  486. ;
  487.     add    cx,14 
  488.     cmp    cx,60
  489.     jge    recv_next
  490.     mov    cx,60
  491. recv_next:
  492.     push    si            ;save si in case we reject it.
  493.     push    bx
  494.     push    cx
  495.  
  496.     push    cs
  497.     pop    es
  498.     mov    di, offset ip_type
  499.     mov    dl,cs:driver_class
  500.     call    recv_find        ;look up our type.
  501.  
  502.     pop    cx
  503.     pop    bx
  504.     pop    si
  505.     mov    ax,es            ;is this pointer null?
  506.     or    ax,di
  507.  
  508.     jne  nb_next 
  509.         jmp  skip_copy 
  510. nb_next:
  511.     push bx
  512.     push cx
  513.     push es
  514.     push di
  515. ;
  516. ; Fix up the Ethernet header added to the incoming packet.
  517. ;
  518.     call    fix_header
  519. ;
  520. ; Copy the received packet into buffer allocated by the application
  521. ; software.
  522. ;
  523.     sub    cx,14
  524.         mov     si,[bx].ncb_buffer.offs
  525.     cld
  526.         rep     movsb
  527.     pop si
  528.     pop ds
  529.     pop cx
  530.     assume ds:nothing
  531.         call    recv_copy
  532.     push cs
  533.     pop ds
  534.     assume ds:code
  535.     pop bx
  536. skip_copy:
  537.         mov     [bx].ncb_length,MAX_DG  ; reestablish dg-length
  538. ;
  539. ; Set up to receive another packet.  Construct "receive datagram"
  540. ; NCB.
  541. ;
  542.         push    ds
  543.         pop     es
  544.         int    5ch
  545. ;
  546. ; Check return code.  Print error indication if NETBIOS does not
  547. ; accept NCB.
  548. ;
  549.         mov    al,[bx].ncb_retcode   ; JS added return code
  550.         cmp     al,0ffh
  551.         jz      nbint_pending_ok1
  552.         mov     al,'?'
  553.         call    tty
  554.         add     ax,32
  555.         call    tty
  556.         mov     al,'.'
  557.         call    tty
  558.  
  559. nbint_pending_ok1:
  560.         jmp     short nbint_done
  561.  
  562. bad_nbint:
  563.         add     ax,32
  564.         call    tty
  565.         mov     al,'R'
  566.         call    tty
  567.     jmp    skip_copy
  568.  
  569. nbint_done:
  570.         pop ds
  571.         iret
  572. nbint   endp
  573.  
  574. ;
  575. ; Set destination and source addressess and packet type in an
  576. ; Ethernet header.
  577. ;
  578. fix_header:
  579. ;
  580. ; Set destination address.
  581. ;
  582.     push    cx
  583.     mov    ax,0000h
  584.     stosw
  585.     mov    ax,0c3c4h
  586.     stosw
  587.     mov    ax,0c2cch
  588.     stosw
  589. ;
  590. ; Set source address.  NCB callname contains the string "TCPIP" +
  591. ; source host IP address.  Extract host IP address and copy into
  592. ; Ethernet header as the source address.
  593. ;
  594.     mov    ax,0000h
  595.     stosw
  596.     mov    ax,word ptr [bx].ncb_callname+5
  597.     stosw
  598.     mov    ax,word ptr [bx].ncb_callname+7
  599.     stosw
  600. ;
  601. ; Set packet type to IP.
  602. ;
  603.     mov    ax, 0008h
  604.     stosw    
  605.  
  606.     pop    cx
  607.     ret
  608.  
  609.  
  610.  
  611.         public  nb_stop
  612. nb_stop:
  613.         ;                   unregister name
  614.         push    cs
  615.         pop     es
  616.         lea      bx,nbrcv1
  617.         mov     [bx].ncb_command,NCB_DELNAME
  618. ;        mov     al,lana_num
  619. ;        mov     [bx].ncb_lana_num,al
  620.         int     5ch
  621.         cmp     al,0
  622.         jz      good_delete
  623.         add     ax,32
  624.         call    tty
  625.         mov     al,'I'
  626.         call    tty
  627. good_delete:
  628.         ret
  629.  
  630.  
  631.     public tty
  632. tty:
  633.         push    bx
  634.         mov     ah,14
  635.         int     10h
  636.         pop     bx
  637.         ret
  638.  
  639. ip_to_nbname:
  640.         ;      call with es:di = *ncb_name
  641.         ;            bx and dx = ip_address
  642.  
  643.         mov     cx,5
  644.         mov     si,offset prefix
  645.         rep     movsb
  646.  
  647.         mov     [di],bx
  648.         mov     [di+2],dx
  649.         ret
  650.  
  651.     public    recv_exiting
  652. recv_exiting:
  653. ;called from the recv isr after interrupts have been acknowledged.
  654. ;Only ds and ax have been saved.
  655.     assume    ds:nothing
  656.     ret
  657.  
  658.  
  659. ;any code after this will not be kept after initialization.
  660.         public end_resident ; MAP
  661. end_resident    label   byte
  662.  
  663.  
  664.         public  usage_msg
  665. usage_msg       db      "usage: nb <packet_int_no> <ip.ad.dr.ess> [receive queue size]",CR,LF,'$'
  666.  
  667.         public  copyright_msg
  668. copyright_msg   db      "Packet driver for a netbios device, version ",'0'+version,CR,LF,'$'
  669.                 db      "Portions Copyright 1990, Michael Haberler",CR,LF,'$'
  670.  
  671. ip_adress_name  db      "IP Adress ",'$'
  672. rq_size_name    db      "Receive Queue ",'$'
  673. bad_name_msg    db      " bad returncode from nb add_name",CR,LF,'$'
  674. bad_rcv_msg     db      " bad returncode from nb receive dg",CR,LF,'$'
  675. good_name_msg   db      " good returncode from nb add_name",CR,LF,'$'
  676. good_rcv_msg    db      " good returncode from nb receive dg",CR,LF,'$'
  677. temp_dw         dw      ?
  678.         extrn   set_recv_isr: near
  679.  
  680. ;enter with si -> argument string, di -> word to store.
  681. ;if there is no number, don't change the number.
  682.         extrn   get_number: near
  683.     extrn    skip_blanks: near
  684.  
  685.         public  parse_args
  686. parse_args:
  687. ;exit with nc if all went well, cy otherwise.
  688.     call    skip_blanks
  689.     cmp    al,'-'            ;did they specify a switch?
  690.     jne    not_switch
  691.     cmp    byte ptr [si+1],'g'    ;did they specify '-g'?
  692.     je    got_gw_switch
  693.     stc                ;no, must be an error.
  694.     ret
  695. got_gw_switch:
  696.     mov    gw_switch,1
  697.     add    si,2            ;skip past the switch's characters.
  698.     jmp    parse_args        ;go parse more arguments.
  699. not_switch:
  700.  
  701.         mov     di, offset temp_dw
  702.         mov     bx, offset ip_adress_name
  703.         call    get_number
  704.         mov     ax,temp_dw
  705.         mov     byte ptr ip_adress+0,al
  706.         inc     si
  707.         mov     di, offset temp_dw
  708.         mov     bx, offset ip_adress_name
  709.         call    get_number
  710.         mov     ax,temp_dw
  711.         mov     byte ptr ip_adress+1,al
  712.         inc     si
  713.         mov     di, offset temp_dw
  714.         mov     bx, offset ip_adress_name
  715.         call    get_number
  716.         mov     ax,temp_dw
  717.         mov     byte ptr ip_adress+2,al
  718.         inc     si
  719.         mov     di, offset temp_dw
  720.         mov     bx, offset ip_adress_name
  721.         call    get_number
  722.         mov     ax,temp_dw
  723.         mov     byte ptr ip_adress+3,al
  724.  
  725.         ret
  726.  
  727.  
  728.  
  729.         public  etopen
  730. etopen:
  731.         pushf
  732.         cld
  733.  
  734. ;if all is okay,
  735. ;        mov     bx,offset nbsend
  736.         lea     bx,nbsend
  737.         mov     [bx].ncb_command,NCB_ADDNAME
  738.         mov     al,lana_num
  739.         mov     [bx].ncb_lana_num,al
  740.  
  741.         push    ds
  742.         push    cs
  743.         push    cs
  744.         pop     ds
  745.         pop     es
  746.  
  747.         push    bx
  748.         lea     di,nbsend.ncb_name
  749.         mov     bx,ip_adress
  750.         mov     dx,ip_adress+2
  751.         call    ip_to_nbname
  752.         pop     bx
  753.  
  754. ;    mov    di, offset nbsend.ncb_name
  755. ;    mov    cx,16
  756. ;mike:
  757. ;    mov    al, [di]
  758. ;    call    tty
  759. ;    inc    di
  760. ;    dec    cx
  761. ;    jnz    mike
  762.  
  763.  
  764.         mov     cx,16
  765.         mov     di,offset nbrcv1.ncb_name
  766.         mov     si,offset nbsend.ncb_name
  767.         rep     movsb
  768.         mov     cx,16
  769.         mov     di,offset nbrcv2.ncb_name
  770.         mov     si,offset nbsend.ncb_name
  771.         rep     movsb
  772.  
  773.         int     5ch     ; add_name, -> returns rc in al
  774.         cmp     al,0
  775.         jz      good_name
  776.         mov     dx,0
  777.         mov     ah,0
  778.         call    dwordout
  779.         mov     dx,offset bad_name_msg
  780.         pop     ds
  781.         jmp     error
  782.  
  783. good_name:
  784. ;        mov     dx,offset good_name_msg
  785. ;        call    say
  786.  
  787.         mov     al,[bx].ncb_num
  788.         mov     local_ncb_num,al
  789.         mov     [bx].ncb_command,NCB_SDATAGRAM  ;set send command code
  790.  
  791.         ;       start receive operations
  792. ;        mov     bx,offset nbrcv1
  793.         lea     bx,nbrcv1
  794.         mov     al,NCB_RDATAGRAM+NCB_NOWAIT  ;set rcv command
  795.         mov     [bx].ncb_command,al
  796.  
  797.         mov     al,local_ncb_num
  798.         mov     [bx].ncb_num,al
  799.  
  800.         mov     ax,MAX_DG
  801.         mov     [bx].ncb_length,ax
  802.  
  803.         mov     ax,ds
  804.         mov     [bx].ncb_buffer.segm,ax
  805.         mov     [bx].ncb_buffer.offs,offset rcv_buffer1
  806.  
  807.         mov     [bx].ncb_post.segm,ax
  808.         mov     [bx].ncb_post.offs,offset nbint
  809.  
  810.         mov     al,lana_num
  811.         mov     [bx].ncb_lana_num,al
  812.         int     5ch
  813.  
  814.         cmp     al,0ffh
  815.         jz      pending_ok1
  816.         cmp     al,00h
  817.         jnz     bad_init
  818.  
  819. pending_ok1:
  820.         mov     dx,offset good_rcv_msg
  821.         call    say
  822.  
  823.         mov     dx,offset end_resident
  824.         pop     ds
  825.         popf
  826.         clc
  827.         ret
  828. ;if we got an error,
  829. bad_init:
  830.         mov     ah,0
  831.         mov     dx,0
  832.         call    dwordout
  833.         mov     dx,offset bad_rcv_msg
  834.         call    say
  835.         call    nb_stop
  836.         pop     ds
  837.         popf
  838.         stc
  839.         ret
  840.  
  841.     public    print_parameters
  842. print_parameters:
  843.     ret
  844.  
  845. say:
  846.         mov     ah,9
  847.         int     21h
  848.         ret
  849.  
  850.  
  851. code    ends
  852.  
  853.     end
  854.